package com.dubbo.hyp.filter;

import com.dubbo.hyp.dto.MethodUseTime;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


@Activate(group = {CommonConstants.CONSUMER})
public class TPMonitorFilter implements Filter, Runnable {

    /**
     * 存放方法与所耗时的集合
     */
    private Map<String, List<MethodUseTime>> methodUseTimeMap = new ConcurrentHashMap<>();

    public TPMonitorFilter() {
        // 创建定时线程，每隔5s打印一次最近1分钟内每个方法的TP90、TP99的耗时情况
        Executors.newSingleThreadScheduledExecutor()
                .scheduleWithFixedDelay(this, 5, 5, TimeUnit.SECONDS);
    }

    @Override
    public void run() {
        System.out.println();
        long endTime = System.currentTimeMillis();
        long startTime = endTime - 60000;
        for (Map.Entry<String, List<MethodUseTime>> methodUseTimeInfo : methodUseTimeMap.entrySet()) {
            List<Long> longList = new LinkedList<>();
            List<MethodUseTime> methodUseTimeList = methodUseTimeInfo.getValue();
            /*methodUseTimeList.forEach(methodUseTime -> {
                if (methodUseTime.getEndTime() >= startTime && methodUseTime.getEndTime() <= endTime) {
                    longList.add(methodUseTime.getUseTime());
                }
            });*/
            for(MethodUseTime methodUseTime:methodUseTimeList){
                if (methodUseTime.getEndTime() >= startTime && methodUseTime.getEndTime() <= endTime) {
                    longList.add(methodUseTime.getUseTime());
                }
            }

            //排序
            for (int i = 1; i < longList.size(); i++) {
                for (int j = i - 1; j >= 0 && longList.get(j) > longList.get(j + 1); j--) {
                    long a = longList.get(j);
                    longList.set(j, longList.get(j + 1));
                    longList.set(j + 1, a);
                }
            }

            //求TP90与TP99的时间
            int index90 = (int) (longList.size() * 0.9);
            int index99 = (int) (longList.size() * 0.99);

            System.out.println(endTime + "--方法名：" + methodUseTimeInfo.getKey()+"符合条件请求有"+longList.size() + "条---TP90耗时为" + longList.get(index90) + "、TP99耗时为" + longList.get(index99));

        }
    }


    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime = System.currentTimeMillis();
        try {
            // 执行方法
            return invoker.invoke(invocation);
        } finally {
            String name = invocation.getMethodName();
            MethodUseTime methodUseTime = new MethodUseTime();
            methodUseTime.setEndTime(System.currentTimeMillis());
            methodUseTime.setUseTime(System.currentTimeMillis() - startTime);
            methodUseTime.setMethodName(name);
            if (methodUseTimeMap.containsKey(name)) {
                methodUseTimeMap.get(name).add(methodUseTime);
            } else {
                List<MethodUseTime> list = new LinkedList<>();
                list.add(methodUseTime);
                methodUseTimeMap.put(name, list);
            }
        }
    }


}
